package com.android.enjoymax;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class MTDAppActivity extends MapActivity {
	public static final String URL = "http://developer.cumtd.com/api/v2.1/json/";
	public static final String KEY = "a3a39b0aecb74c0f992b5c5bdc15674f";
	
	public static final int NUM_BUS_STOPS = 4;
	public static final int NUM_DEPARTURES = 3;
	
    public static final String TAG = "Loc";
    public static final String CURRENT_LOCATION = "Current Location";
    public static final String MILES = " miles";
    
    public static final long MIN_TIME = 60000;
    public static final float MIN_DISTANCE = 100;
    public static final int ZOOM_LEVEL = 18;
    public static final double FEET_TO_MILES = 0.3048 * 0.00062137119;
    public static 
    
	double latitude = 0.0;
	double longitude = 0.0;
	
	private boolean intentReturn = false;
	
	private LocationManager lm;
	private MyLocationListener locationListener;
	private MapController mapController;
	private SensorManager mSensorManager;
	private GeoPoint pointPresent;
	private MyItemizedOverlay itemizedOverlay;
	private MyItemizedOverlay itemizedOverlayForCurrentLoc;
	private List<Overlay> mapOverlays; 
	
	private ListView listView;
	private ArrayAdapter<String> adapter;
	
    public static boolean flag = true;
	
    private static MTDAppActivity temp;
    
    public static List<String> globalStopIds= new ArrayList<String>();
    
    private static String stopIdSelected;
    
	/** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
//        setContentView(R.layout.mtdappactivity);  
        
        temp = this;
        lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        locationListener = new MyLocationListener();
        
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME, MIN_DISTANCE, locationListener);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DISTANCE, locationListener);
        
        // Set Map Parameters.
        MapView mapView = (MapView) findViewById(R.id.mapview);
    	mapView.setStreetView(true);
    	mapView.setTraffic(true);
    	mapView.setBuiltInZoomControls(true);
    	mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    	
    	mapOverlays = mapView.getOverlays();
		Drawable drawable = this.getResources().getDrawable(R.drawable.pushpin);
		Drawable forCurrent = this.getResources().getDrawable(R.drawable.mylocation);
		
		//itemizedOverlay = new MyItemizedOverlay(drawable);
		itemizedOverlay = new MyItemizedOverlay(drawable, this);
		itemizedOverlayForCurrentLoc = new MyItemizedOverlay(forCurrent, this);
		
		mapController = mapView.getController();
    	mapController.setZoom(ZOOM_LEVEL);
    } 
    
    public static MTDAppActivity get() {
    	return temp;
    }
    
    @Override
	protected boolean isRouteDisplayed() {
    	
		// TODO Auto-generated method stub	
    	
		return false;
	}
    
    private GeoPoint coordinatesToGeoPoint(Location location) {
    	final int multiplier = (int) Math.pow(10, 6);
    	final int tempLatitude = (int)(location.getLatitude() * multiplier);
    	final int tempLongitude = (int) (location.getLongitude() * multiplier);
    	
    	System.out.println(tempLatitude + " "+ tempLongitude);
    	return new GeoPoint(tempLatitude, tempLongitude);
    }
    
    private GeoPoint coordinatesToGeoPoint(double latitudeLoc, double longitudeLoc) {
    	final int multiplier = (int) Math.pow(10, 6);
    	final int tempLatitude = (int)(latitudeLoc * multiplier);
    	final int tempLongitude = (int) (longitudeLoc * multiplier);
    	
    	//System.out.println(tempLatitude + " "+ tempLongitude);
    	return new GeoPoint(tempLatitude, tempLongitude);
    }

    private void addOverlay(GeoPoint pinCoordinates, String title, String snippet) {
    	OverlayItem overlayItem = new OverlayItem(pinCoordinates, title, snippet);
    	
//    	if (place.equals(CURRENT_LOCATION)) {
//    	    if (mapOverlays.size() != 0) {
//    	    	mapOverlays.remove(0);
//    	    }
//    	    
//    	    itemizedOverlay.addOverlay(overlayItem);
//    	    
//    	    mapOverlays.add(0, itemizedOverlay);
//    	    
//    	    return;
//    	}
//    	
    	if(title.equals(CURRENT_LOCATION)) {
    		itemizedOverlayForCurrentLoc.addOverlay(overlayItem);
    		mapOverlays.add(itemizedOverlayForCurrentLoc);
    	}
    	else {
            itemizedOverlay.addOverlay(overlayItem);
            mapOverlays.add(itemizedOverlay);
    	}
    }
    
    class MyLocationListener implements LocationListener 
    {

    	
		@Override
		public void onLocationChanged(Location location) {
			longitude = location.getLongitude();
	        latitude = location.getLatitude();
	        
	         Log.d(TAG, "my lat is " + latitude + " and lon is " + longitude);
	         
	         itemizedOverlayForCurrentLoc.resetMap();
	         pointPresent = coordinatesToGeoPoint(location);
	         
	         //Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
	         mapController.animateTo(pointPresent);
	         mapController.setCenter(pointPresent);
	         addOverlay(pointPresent, CURRENT_LOCATION, "");
	         
	         new RequestTask().execute(new String[] {URL + "GetStopsByLatLon", "GetStopsByLatLon"});
		}

		@Override
		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			
			//new RequestTask().execute(new String[] {URL + "GetStopsByLatLon", "GetStopsByLatLon"});
		}
        	
    }
    
    // This is for GetStopsByLatLon webservice call.
    class RequestTask extends AsyncTask<String, Void, String>{
    	
        @Override
        protected String doInBackground(String... uri) {
        	
        	if (uri[1].equals("GetStopsByLatLon")) {
        		RestClient client = new RestClient(uri[0]);
        		client.addParam("key", KEY);
        		client.addParam("lat", String.valueOf(latitude));
        		client.addParam("lon", String.valueOf(longitude));
        		client.addParam("count", String.valueOf(NUM_BUS_STOPS));
        		//client.addParam("changeset_id", "");

        		try {
        		    client.Execute();
        		} 
        		catch (Exception e) {
        			printToast("Network not reachable");
        			return "";
        		    //e.printStackTrace();
        		}

        		String response = client.getResponse();
        		
        		return response;
        	}
        	
        	return "";
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            //Do anything with response..
            
            try {
            	if (result == "" || result.length() == 0) return;
            	
				JSONObject jsonObject = new JSONObject(result);
				
				// For bustop names. For ex - "Springfield and Busey"
				List<String> busStopList = new ArrayList<String>();
				
				// For distances to different bustops from current location.
				List<Double> distanceToBusStopList = new ArrayList<Double>();
				
				// Get the stop ids of the busstops.
				final List<String> stopIds = new ArrayList<String>();
				
				//clear the globalStopIds.
				//globalStopIds.clear();
				
				JSONArray array = jsonObject.getJSONArray("stops");
				ArrayList<NameValuePair> latLonList = new ArrayList<NameValuePair>();
				
				for(int i = 0 ; i < array.length() ; i++){
				    busStopList.add(array.getJSONObject(i).getString("stop_name"));
				    distanceToBusStopList.add(array.getJSONObject(i).getDouble("distance"));
				    stopIds.add(array.getJSONObject(i).getString("stop_id"));
				    globalStopIds.add(array.getJSONObject(i).getString("stop_id"));
				    
				    JSONArray jLatLonArray = array.getJSONObject(i).getJSONArray("stop_points");
				    double stopLat = jLatLonArray.getJSONObject(0).getDouble("stop_lat");
				    double stopLon = jLatLonArray.getJSONObject(0).getDouble("stop_lon");
				    
				    GeoPoint tempPoint = coordinatesToGeoPoint(stopLat, stopLon);
				    
				    Log.d(TAG, "About to add an ovelay for " + stopLat + " and " + stopLon);
				    int dist = (int) (array.getJSONObject(i).getDouble("distance") * FEET_TO_MILES * 100);
				    addOverlay(tempPoint, array.getJSONObject(i).getString("stop_name"), String.valueOf((double)(dist)/100) + MILES);
				}
				
				listView = (ListView) findViewById(R.id.mylist);
				
				String[] values = new String[busStopList.size()];
				
//				for (int i = 0; i < busStopList.size(); i++) {
//					int dist = (int) (distanceToBusStopList.get(i) * FEET_TO_MILES * 100);
//					values[i] = busStopList.get(i) + "\n" + (double)(dist)/100 + MILES;
//				}

				// First paramenter - Context
				// Second parameter - Layout for the row
				// Third parameter - ID of the View to which the data is written
				// Forth - the Array of data
//				adapter = new ArrayAdapter<String>(getApplicationContext(),
//					android.R.layout.simple_list_item_1, android.R.id.text1, values);

//				
//				listView.setOnItemClickListener(new OnItemClickListener() {
//					@Override
//					public void onItemClick(AdapterView<?> parent, View view,
//						int position, long id) {
//						
//						new GetDeparturesByStopHandler().execute(URL + "GetDeparturesByStop", stopIds.get(position));
//					
//					}
//
//				});
				
				// Assign adapter to ListView
			//	listView.setAdapter(adapter);
				
				Context context = getApplicationContext();
				int duration = Toast.LENGTH_LONG;

				Toast toast = Toast.makeText(context, "Select a stop from the Map", duration);
				toast.setGravity(Gravity.BOTTOM, 0, 0);
				toast.show();
				
			} 
            catch (JSONException e) {
				// TODO Auto-generated catch block
            	//printToast("Not able to parse JSON due to invalid input");
				//e.printStackTrace();
			}

        }
    }
    
    void printToast(String str) {
    	Context context = getApplicationContext();
		int duration = Toast.LENGTH_LONG;

		Toast toast = Toast.makeText(context, str, duration);
		toast.setGravity(Gravity.CENTER, 0, 0);
		toast.show();	
    }
    
    // Class to handle GetDeparturesByStop webservice call.
    class GetDeparturesByStopHandler extends AsyncTask<String, Void, String> 
    {

		@Override
		protected String doInBackground(String... uri) {
			
			RestClient client = new RestClient(uri[0]);
			stopIdSelected = uri[1];
			client.addParam("key", KEY);
    		client.addParam("stop_id", uri[1]);
    		client.addParam("count", String.valueOf(NUM_DEPARTURES));

    		try {
    		    client.Execute();
    		} 
    		catch (Exception e) {
    			printToast("Network not reachable");
    		    //e.printStackTrace();
    		}

    		String response = client.getResponse();
    		
    		return response;
		}
		
		protected void onPostExecute(String result) {
			
            super.onPostExecute(result);
            //Do anything with response..
            
		   try {
			JSONObject jsonObject = new JSONObject(result);
			
			JSONArray array = jsonObject.getJSONArray("departures");
			
			final List<String> busNumbers = new ArrayList<String>();
			List<Double> expectedTimes = new ArrayList<Double>();
			
			for (int i = 0; i < array.length(); i++) {
				busNumbers.add(array.getJSONObject(i).getString("headsign"));
			    expectedTimes.add(array.getJSONObject(i).getDouble("expected_mins"));	
				
			}
			
			String[] values = new String[busNumbers.size()];
			
			for (int i = 0; i < busNumbers.size(); i++) {
				values[i] = busNumbers.get(i) + "\n" + expectedTimes.get(i) + " minutes";
			}
			
			ArrayAdapter<String> tempAdapter = new ArrayAdapter<String>(getApplicationContext(),
					android.R.layout.simple_list_item_1, android.R.id.text1, values);
			
		//	ArrayAdapter<String> tempAdapter = new ArrayAdapter<String>(getApplicationContext(),
			//		android.R.layout.simple_list_item_1, android.R.id.text1);
			
			listView.setOnItemClickListener(new OnItemClickListener() {
				@Override
				public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
					
					Intent i = new Intent(getApplicationContext(), MTDAppActivity.class);
					i.putExtra("stop_id", stopIdSelected);
					i.putExtra("bus_number", busNumbers.get(position));
//					i.putExtra("stop_id", "SPLDBSY");
//					i.putExtra("bus_number", "130S");
					startActivity(i);
					Log.d(MTDAppActivity.TAG, "Back to mtd app " + i);
					intentReturn = true;
					//this.
					//mapController.animateTo(pointPresent);
//					finish();
				}
			});
			
			//tempAdapter.add("Testing");
			
				// Assign adapter to ListView
		    listView.setAdapter(tempAdapter);
				
		   } 
		   catch (JSONException e) {
			// TODO Auto-generated catch block
			  // printToast("Unable to Parse JSON");
			//e.printStackTrace();
		}
            
    }
}  

    @Override
    public void onResume() {
        super.onResume();
        //if(D) 
        Log.d(TAG, "+ ON RESUME +");
        
        if (intentReturn == true) {
        	mapController.animateTo(pointPresent);
        	intentReturn = false;
        	new RequestTask().execute(new String[] {URL + "GetStopsByLatLon", "GetStopsByLatLon"});
        }
    }
 
}